<?php
class Core_Model_Router_Standard extends Core_Model_Router {

	const CONFIG_ROUTE_PATH = 'routes';

	protected $_routerName = 'standard';

	protected $_modules = array();
	
	protected $_request;

	public function process(Core_Model_Http_Request $request) {
		$this->_request = $request;
		
		$this->_collectRoute();
		
		// get route paths
		$p = explode('/', $this->_getDefaultPathInfo());
		if ($pi = trim($request->getPathInfo(), '/'))
			$p = array_replace($p, explode( '/', $pi));

		// get front name
		$frontName = $request->getFrontName() ? $request->getFrontName() : $p[0];

		// get controller
		$controller = $request->getControllerName() ? $request->getControllerName() : $p[1];
		
		// get action
		$action = $request->getActionName() ? $request->getActionName() : $p[2];
		
		// get controller instance
		$controllerInstance = $this->_getControllerInstance($frontName, $controller, $action);
		if (!$controllerInstance) return;

		// set parameters from pathinfo
		for ($i = 3, $l = count($p); $i < $l; $i += 2) {
			$request->setRouteParam($p[$i], isset($p[$i+1]) ? urldecode($p[$i+1]) : '');
		}

		// set values only after all the checks are done
		$request
			->setFrontName($frontName)
			->setControllerName($controller)
			->setActionName($action)
			->setDispatched(true);

		// start controller action
		$controllerInstance->dispatch($action);
	}
	
	protected function _collectRoute() {
		// sort routes by order
		$config = Mag::getConfig();
		$config->sortConfig(self::CONFIG_ROUTE_PATH, 'order');
		$routes = Mag::helper('Core')->searchTable( $config->get(self::CONFIG_ROUTE_PATH), 'router', $this->_routerName );

		// get all routes of standard router
		foreach($routes as $name => $data) {
			$this->_modules[$data['front_name']][] = $data['module'];
		}
	}
	
	public function getRequest() {
		return $this->_request;
	}
	
	protected function _getDefaultPathInfo() {
		$result = 'core/index/index';
		return $result;
	}

	protected function _getModulesByFrontName($frontName) {
		if (isset($this->_modules[$frontName]))
			return $this->_modules[$frontName];
		return false;
	}

	protected function _getControllerInstance($frontName, $controller, $action) {
		$modules = $this->_getModulesByFrontName($frontName);
		if (!$modules) return null;

		foreach ($modules as $moduleName) {
			$controllerClass = $this->getControllerClass($moduleName, $controller);
			$controllerFile = Mag::getIncludeFilename($controllerClass);
			if (!is_readable($controllerFile)) continue;
			require_once($controllerFile);
			if (!class_exists($controllerClass)) continue;

			$controllerInstance = Mag::singleton($controllerClass);
			if ($controllerInstance->hasAction($action))
				return $controllerInstance;
		}
		return null;
	}

	public function getControllerClass($module, $controller) {
		return $module . '_Controller_' . Mag::helper('Core')->ucwords($controller);
	}

}